﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Threading;
namespace LCL.LogNet
{
    /// <summary>
    /// 一个通用的日志接口
    /// </summary>
    /// <remarks>
    /// 本组件的日志核心机制，如果您使用了本组件却不想使用本组件的日志组件功能，可以自己实现新的日志组件，
    /// 只要继承本接口接口。其他常用的日志组件如下：（都是可以实现的）
    /// <list type="number">
    /// <item>Log4Net</item>
    /// <item>NLog</item>
    /// </list>
    /// </remarks>
    public interface ILogNet : IDisposable
    {
        /// <summary>
        /// 文件存储模式，1:单文件，2:根据大小，3:根据时间
        /// </summary>
        int LogSaveMode { get; }
        /// <summary>
        /// 存储之前引发的事件，允许额外的操作
        /// </summary>
        event EventHandler<LogEventArgs> BeforeSaveToFile;
        /// <summary>
        /// 自定义的消息记录
        /// </summary>
        /// <param name="degree">消息等级</param>
        /// <param name="keyWord">关键字</param>
        /// <param name="text">日志内容</param>
        void RecordMessage(LogLevel degree, string keyWord, string text);
        /// <summary>
        /// 写入一条调试日志
        /// </summary>
        /// <param name="text">日志内容</param>
        void Debug(string text);
        /// <summary>
        /// 写入一条调试日志
        /// </summary>
        /// <param name="keyWord">关键字</param>
        /// <param name="text">日志内容</param>
        void Debug(string keyWord, string text);
        /// <summary>
        /// 写入一条解释性的信息
        /// </summary>
        /// <param name="description"></param>
        void Descrition(string description);
        /// <summary>
        /// 写入一条错误日志
        /// </summary>
        /// <param name="text">日志内容</param>
        void Error(string text);
        /// <summary>
        /// 写入一条错误日志
        /// </summary>
        /// <param name="keyWord">关键字</param>
        /// <param name="text">日志内容</param>
        void Error(string keyWord, string text);
        /// <summary>
        /// 写入一条异常信息
        /// </summary>
        /// <param name="keyWord">关键字</param>
        /// <param name="ex">异常</param>
        void Exception(string keyWord, Exception ex);
        /// <summary>
        /// 写入一条异常信息
        /// </summary>
        /// <param name="keyWord">关键字</param>
        /// <param name="text">内容</param>
        /// <param name="ex">异常</param>
        void Exception(string keyWord, string text, Exception ex);
        /// <summary>
        /// 写入一条致命日志
        /// </summary>
        /// <param name="text">日志内容</param>
        void Fatal(string text);
        /// <summary>
        /// 写入一条致命日志
        /// </summary>
        /// <param name="keyWord">关键字</param>
        /// <param name="text">日志内容</param>
        void Fatal(string keyWord, string text);
        /// <summary>
        /// 写入一条信息日志
        /// </summary>
        /// <param name="text">日志内容</param>
        void Info(string text);
        /// <summary>
        /// 写入一条信息日志
        /// </summary>
        /// <param name="keyWord">关键字</param>
        /// <param name="text">日志内容</param>
        void Info(string keyWord, string text);
        /// <summary>
        /// 写入一行换行符
        /// </summary>
        void NewLine();
        /// <summary>
        /// 写入一条警告日志
        /// </summary>
        /// <param name="text">日志内容</param>
        void Warn(string text);
        /// <summary>
        /// 写入一条警告日志
        /// </summary>
        /// <param name="keyWord">关键字</param>
        /// <param name="text">日志内容</param>
        void Warn(string keyWord, string text);
        /// <summary>
        /// 设置日志的存储等级，高于该等级的才会被存储
        /// </summary>
        /// <param name="degree">登记信息</param>
        void SetMessageDegree(LogLevel degree);
        /// <summary>
        /// 获取已存在的日志文件名称
        /// </summary>
        /// <returns>文件列表</returns>
        string[] GetExistLogFileNames();
        /// <summary>
        /// 过滤掉指定的关键字的日志，该信息不存储，但仍然触发BeforeSaveToFile事件
        /// </summary>
        /// <param name="keyword">关键字</param>
        void FiltrateKeyword(string keyword);
    }
    /// <summary>
    /// 带有日志消息的事件
    /// </summary>
    public class LogEventArgs : EventArgs
    {
        /// <summary>
        /// 消息信息
        /// </summary>
        public LogInfo HslMessage { get; set; }
    }
    /// <summary>
    /// 单个日志的记录信息
    /// </summary>
    public class LogInfo
    {
        private static long IdNumber = 0;
        /// <summary>
        /// 默认的无参构造器
        /// </summary>
        public LogInfo()
        {
            Id = Interlocked.Increment(ref IdNumber);
            Degree= LogLevel.DEBUG;
        }
        /// <summary>
        /// 单个记录信息的标识ID，程序重新运行时清空
        /// </summary>
        public long Id { get; private set; }
        /// <summary>
        /// 消息的等级
        /// </summary>
        public LogLevel Degree { get; set; } 
        /// <summary>
        /// 线程ID
        /// </summary>
        public int ThreadId { get; set; }
        /// <summary>
        /// 消息文本
        /// </summary>
        public string Text { get; set; }
        /// <summary>
        /// 消息发生的事件
        /// </summary>
        public DateTime Time { get; set; }
        /// <summary>
        /// 消息的关键字
        /// </summary>
        public string KeyWord { get; set; }
        /// <summary>
        /// 返回表示当前对象的字符串
        /// </summary>
        /// <returns>字符串信息</returns>
        public override string ToString( )
        {
            if (string.IsNullOrEmpty( KeyWord ))
            {
                return "["+Degree+"] "+Time.ToString("yyyy-MM-dd HH:mm:ss.fff")+" Thread ["+ThreadId.ToString( "D2" )+"] "+Text+"";
            }
            else
            {
                 return "["+Degree+"] "+Time.ToString("yyyy-MM-dd HH:mm:ss.fff")+" Thread ["+ThreadId.ToString( "D2" )+"] "+KeyWord+":"+Text+"";
            }
        }
        /// <summary>
        /// 返回表示当前对象的字符串，剔除了关键字
        /// </summary>
        /// <returns>字符串信息</returns>
        public string ToStringWithoutKeyword()
        {
            return "[" + Degree + "] " + Time.ToString("yyyy-MM-dd HH:mm:ss.fff") + " Thread [" + ThreadId.ToString("D2") + "] " + Text + "";
        }
    }
    /// <summary>
    /// 记录消息的等级
    /// </summary>
    public enum LogLevel
    {
        /// <summary>
        /// 一条消息都不记录
        /// </summary>
        None = 1,
        /// <summary>
        /// 记录致命等级及以上日志的消息
        /// </summary>
        FATAL = 2,
        /// <summary>
        /// 记录异常等级及以上日志的消息
        /// </summary>
        ERROR = 3,
        /// <summary>
        /// 记录警告等级及以上日志的消息
        /// </summary>
        WARN = 4,
        /// <summary>
        /// 记录信息等级及以上日志的消息
        /// </summary>
        INFO = 5,
        /// <summary>
        /// 记录调试等级及以上日志的信息
        /// </summary>
        DEBUG = 6,
        TRACE=7,
    }
    /// <summary>
    /// 日志文件输出模式
    /// </summary>
    public enum GenerateMode
    {
        /// <summary>
        /// 按每个小时生成日志文件
        /// </summary>
        ByEveryHour = 1,
        /// <summary>
        /// 按每天生成日志文件
        /// </summary>
        ByEveryDay = 2,
        /// <summary>
        /// 按每个周生成日志文件
        /// </summary>
        ByEveryWeek = 3,
        /// <summary>
        /// 按每个月生成日志文件
        /// </summary>
        ByEveryMonth = 4,
        /// <summary>
        /// 按每季度生成日志文件
        /// </summary>
        ByEverySeason = 5,
        /// <summary>
        /// 按每年生成日志文件
        /// </summary>
        ByEveryYear = 6,
    }
}
